package com.aabte.springcloudlearn.ribbonhystrixcustomerdemo.controller;

import com.aabte.springcloudlearn.common.beans.User;
import com.aabte.springcloudlearn.common.utils.CommonMethod;
import com.aabte.springcloudlearn.ribbonhystrixcustomerdemo.hystrix.UserCollapseCommand;
import com.aabte.springcloudlearn.ribbonhystrixcustomerdemo.service.UserCustomerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;

/**
 * @author Daniel
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserCustomerController {

    @Autowired
    private UserCustomerService userCustomerService;

    @GetMapping
    public List<User> queryUsers(
            @RequestParam(value = "ids", required = false) List<Long> ids
    ) {
        log.info("Start queryUsers. ids: {}", ids);
        List<User> result = userCustomerService.findAll(ids);
        log.info("End queryUsers. result: {}", result);
        return result;
    }

    @GetMapping("/{id:\\d+}")
    public User queryUserById(
            @PathVariable(name = "id") Long id) {
        log.info("Start queryUserById. id: {}", id);
        User result = userCustomerService.findOne(id);
        log.info("End queryUserById. result: {}", result);
        return result;
    }


    @PostMapping
    public Boolean registerUser(
            @RequestBody @Valid User user) {
        log.info("Start registerUser. user: {}", user);
        Boolean result = userCustomerService.registerUser(user);
        log.info("End registerUser. result: {}", result);
        return result;

    }

    @PutMapping
    public Boolean updateUser(
            @RequestBody @Valid User user) {
        log.info("Start updateUser. user: {}", user);
        Boolean result = userCustomerService.updateUser(user);
        log.info("End updateUser. result: {}", result);
        return result;
    }

    @DeleteMapping("/user/{id:\\d+}")
    public Boolean deleteUserById(
            @PathVariable(name = "id") Long id) {
        log.info("Start deleteUserById. id: {}", id);
        Boolean result = userCustomerService.deleteUser(id);
        log.info("Start deleteUserById. result: {}", result);
        return result;
    }

    /**
     * 合并请求
     * 注意：
     *  只能合并在一次客户端请求内，对某个提供者单个查询接口多次调用
     *  不能合并多次客户端请求内，对某个提供者单个查询接口多次调用
     */
    @GetMapping("/collapse")
    public List<User> collapseQueryUser() {
        log.info("Start collapseQueryUser.");

        List<User> users = new ArrayList<>(4);

        Future<User> userFuture1 = new UserCollapseCommand(userCustomerService, 1L).queue();
        Future<User> userFuture2 = new UserCollapseCommand(userCustomerService, 2L).queue();
        Future<User> userFuture3 = new UserCollapseCommand(userCustomerService, 3L).queue();

        try {
            User user1 = userFuture1.get();
            User user2 = userFuture2.get();
            User user3 = userFuture3.get();
            users.add(user1);
            users.add(user2);
            users.add(user3);
        } catch (Exception e) {
            log.error(CommonMethod.getErrorStack(e));
        }

        log.info("End collapseQueryUser.");
        return users;
    }

    /**
     * 同步方法测试合并请求
     * 说明：这个方法是用来与上面的方法做类比的，
     * 通过这个实验我们发现如果使用同步方法，
     * 那么这个请求合并的作用就没有了
     */
    @GetMapping("/syncCollapse")
    public List<User> syncCollapseQueryUser() {
        log.info("Start syncCollapseQueryUser.");

        List<User> users = new ArrayList<>(4);
        User user1 = new UserCollapseCommand(userCustomerService, 1L).execute();
        User user2 = new UserCollapseCommand(userCustomerService, 2L).execute();
        User user3 = new UserCollapseCommand(userCustomerService, 3L).execute();
        users.add(user1);
        users.add(user2);
        users.add(user3);

        log.info("End syncCollapseQueryUser.");
        return users;
    }

    @GetMapping("/collapseByAnnotation")
    public List<User> collapseByAnnotation(){
        log.info("Start collapseByAnnotation.");

        List<User> result = new ArrayList<>(4);

        Future<User> userFuture1 = userCustomerService.findOneByAnnotation(1L);
        Future<User> userFuture2 = userCustomerService.findOneByAnnotation(2L);
        Future<User> userFuture3 = userCustomerService.findOneByAnnotation(3L);

        try {
            User user1 = userFuture1.get();
            User user2 = userFuture2.get();
            User user3 = userFuture3.get();
            result.add(user1);
            result.add(user2);
            result.add(user3);
        } catch (Exception e) {
            log.error(CommonMethod.getErrorStack(e));
        }

        log.info("End collapseByAnnotation. result: {}", result);
        return result;
    }
}
